using System;
using System.Text.RegularExpressions;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Web.UI.HtmlControls;
using Castle.MonoRail.Framework.Helpers;

namespace Application.Business.Utility  
 {  
	 public static class StringExtension  
	 {  
		 /// <summary>  
		 /// Convert to Integer specifying a default value.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 ///   <param name="defaultValue"></param>  
		 /// <returns></returns>  
		 public static int ToInt(this string str, int defaultValue)  
		 {
			 int res;
			 try
			 {
				 if (!string.IsNullOrEmpty(str))
					 res = int.Parse(str);
				 else
					 res = defaultValue;
			 }
			 catch (OverflowException)
			 {
				 throw;
			 }
			 catch (Exception)
			 {
				 res = defaultValue;
			 }
			 return res;
		 }  
   
		 /// <summary>  
		 /// Convert to Integer.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 /// <returns></returns>  
		 public static int ToInt(this string str)  
		 {
			 return StringExtension.ToInt(str, default(int));
		 }  
   
		 /// <summary>  
		 /// Convert to Long specifying a default value.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 ///   <param name="defaultValue"></param>  
		 /// <returns></returns>  
		 public static long ToLng(this string str, long defaultValue)  
		 {  
			 long res;  
			 try  
			 {  
				 if (!string.IsNullOrEmpty(str))  
					 res = long.Parse(str);  
				 else  
					 res = defaultValue;  
			 }  
			 catch (OverflowException)  
			 {  
				 throw;  
			 }  
			 catch (Exception)  
			 {  
				 res = defaultValue;  
			 }  
			 return res;  
		 }  
   
		 /// <summary>  
		 /// Convert to Long.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 /// <returns></returns>  
		 public static long ToLng(this string str)  
		 {
			 return StringExtension.ToLng(str, default(long));
		 }  
   
		 /// <summary>  
		 /// Convert to Decimal specifying a default value.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 ///   <param name="defaultValue"></param>  
		 /// <returns></returns>  
		 public static decimal ToDec(this string str, decimal defaultValue)  
		 {  
			 decimal res;  
			 if (!string.IsNullOrEmpty(str))  
				 return decimal.TryParse(str, out res) ? res : defaultValue;  
			 else  
				 return defaultValue;  
		 }  
   
		 /// <summary>  
		 /// Convert to Decimal.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 /// <returns></returns>  
		 public static decimal ToDec(this string str)  
		 {
			 return StringExtension.ToDec(str, default(decimal));
		 }  
   
		 /// <summary>  
		 /// Convert to Boolean specifying a default value.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 ///   <param name="defaultValue"></param>  
		 /// <returns></returns>  
		 public static bool ToBool(this string str, bool defaultValue)  
		 {  
			 bool res;  
			 if (!string.IsNullOrEmpty(str))  
				 return bool.TryParse(str, out res) ? res : defaultValue;  
			 else
				 return defaultValue;  
		 }  
   
		 /// <summary>  
		 /// Convert to Boolean.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 /// <returns></returns>  
		 public static bool ToBool(this string str)  
		 {
			 return StringExtension.ToBool(str, default(bool));
		 }  
   
		 /// <summary>  
		 /// Convert to DateTime specifying a default value.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 ///    <param name="defaultValue"></param>  
		 /// <returns></returns>  
		 public static DateTime ToDateTime(this string str, DateTime defaultValue)  
		 {  
			 DateTime res;  
			 if (!string.IsNullOrEmpty(str))  
				 return DateTime.TryParse(str, out res) ? res : defaultValue;  
			 else
				 return defaultValue;  
		 }  
   
		 /// <summary>  
		 /// Convert to DateTime.  
		 /// </summary>  
		 ///   <param name="str"></param>  
		 /// <returns></returns>  
		 public static DateTime ToDateTime(this string str)  
		 {
			 return ToDateTime(str, default(DateTime));
		 }  
   
		 /// <summary>  
		 /// Indicates whether the regular expression finds a match in the input string using the regular expression specified in the pattern parameter.  
		 /// </summary>  
		 ///   <param name="value">String to match</param>  
		 ///   <param name="regularExpression">Regular expression, eg. [a-Z]{3}</param>  
		 ///   <param name="matchEntirely">Return true only if string was matched entirely</param>  
		 /// <returns></returns>  
		 public static bool IsMatch(this string value, string regularExpression, bool matchEntirely)  
		 {  
			 return Regex.IsMatch(value, matchEntirely ? "\\A" + regularExpression + "\\z" : regularExpression);  
		 }  
   
	 }  
   
	 public static class NullableBooleanExtension  
	 {  
		 /// <summary>  
		 /// Convert to Integer specifying a default value.  
		 /// </summary>  
		 ///   <param name="value"></param>  
		 ///   <param name="defaultValue"></param>  
		 /// <returns></returns>  
		 public static int ToInt(this bool? value, int defaultValue)  
		 {  
			 int res;  
			 try  
			 {  
				 res = value.HasValue ? Convert.ToInt32(value) : defaultValue;  
			 }  
			 catch (Exception)  
			 {  
				 res = defaultValue;  
			 }  
			 return res;  
		 }  
   
		 /// <summary>  
		 /// Convert to Integer.  
		 /// </summary>  
		 ///   <param name="value"></param>  
		 /// <returns></returns>  
		 public static int ToInt(this bool? value)  
		 {
			 return NullableBooleanExtension.ToInt(value, default(int));
		 }  
   
	 }  
   
	 public static class ObjectExtension  
	 {  
		 /// <summary>  
		 /// Clone properties from an original object to a destination object.  
		 /// </summary>  
		 /// <typeparam name="T1"></typeparam>  
		 /// <typeparam name="T2"></typeparam>  
		 ///   <param name="origin"></param>  
		 ///   <param name="destination"></param>  
		 public static void CloneProperties<T1, T2>(this T1 origin, T2 destination)  
		 {  
			 // Instantiate if necessary  
			 if (destination == null) throw new ArgumentNullException("destination", "Destination object must first be instantiated.");
			 if (origin == null) throw new ArgumentNullException("origin", "Original object must not be null.");

			 PropertyInfo[] origProperties = origin.GetType().GetProperties();

			 // Loop through each property in the destination  
			 foreach (var destinationProperty in destination.GetType().GetProperties())  
			 {  
				 // find and set val if we can find a matching property name and matching type in the origin with the origin's value  
				 if (destinationProperty.CanWrite)  
				 {  
					 origProperties.Where(x => x.CanRead && x.Name == destinationProperty.Name && x.PropertyType == destinationProperty.PropertyType)  
						 .ForEach(x => destinationProperty.SetValue(destination, x.GetValue(origin, null), null));  
				 }  
			 }  
		 }

		 public static void ForEach<T>(this IEnumerable<T> coll, Action<T> func)
		 {
			 foreach (T t in coll)
				 func(t);
		 }
	 }  
   
	 public static class ValidatorExtension  
	 {  
		 /// <summary>  
		 /// Return true if value is between a range of values.  
		 /// </summary>  
		 /// <returns></returns>  
		 public static bool Between<T>(this IComparable<T> value, T start, T end, bool inclusive)
		 {
			 if (inclusive)
				 return (value.CompareTo(start) >= 0 && value.CompareTo(end) <=0);
			 return (value.CompareTo(start) > 0 && value.CompareTo(end) < 0);
		 }
	 }

	 public static class HtmlHelperExtensions  
	 {  
		 #region HtmlHelper extensions  
			 static readonly Dictionary<double, Func<TimeSpan, string>> relativeTimes = new Dictionary<double, Func<TimeSpan, string>>();
   
		 static HtmlHelperExtensions()
		 {
			 relativeTimes.Add(0.75, (ts) => "less than a minute");
			 relativeTimes.Add(1.5, (ts) => "about a minute");
			 relativeTimes.Add(45, (ts) => string.Format("{0} minutes", Math.Round(ts.TotalMinutes)));
			 relativeTimes.Add(90, (ts) => "about an hour");
			 relativeTimes.Add(1440, (ts) => string.Format("about {0} hours", Math.Round(Math.Abs(ts.TotalHours)))); // 60 * 24  == < 1 day
			 relativeTimes.Add(2880, (ts) => "a day"); // 60 * 48  == < 2 days
			 relativeTimes.Add(43200, (ts) => string.Format("{0} days", Math.Floor(Math.Abs(ts.TotalDays)))); // 60 * 24 * 30  == < 30 days
			 relativeTimes.Add(86400, (ts) => "about a month"); // 60 * 24 * 60    == < 60 days
			 relativeTimes.Add(525600, (ts) => string.Format("{0} months", Math.Floor(Math.Abs(ts.TotalDays / 30)))); // 60 * 24 * 365  == < 1 year
			 relativeTimes.Add(1051200, (ts) => "about a year"); // 60 * 24 * 365 * 2   == < 2 years
			 relativeTimes.Add(double.MaxValue, (ts) => string.Format("{0} years", Math.Floor(Math.Abs(ts.TotalDays / 365))));  // == < forever

		 }
		 /// <summary>  
		 /// Format date/time object into html representation of 'relative time' format, eg. "5 seconds ago".  
		 /// </summary>  
		 ///   <param name="htmlHelper"></param>  
		 ///   <param name="value"></param>  
		 /// <returns></returns>  
		 public static string FormatDateTimeRelative(this FormHelper htmlHelper, DateTime value)  
		 {  
				 // As suggested on stackoverflow.com and found to be the most comprehensive method.  
				 // http://stackoverflow.com/questions/11/how-do-i-calculate-relative-time  
   
				 TimeSpan oSpan = DateTime.Now.Subtract(value);  
				 double TotalMinutes = oSpan.TotalMinutes;  
				 string Suffix = " ago";  
   
				 if (TotalMinutes < 0.0)  
				 {  
					 TotalMinutes = Math.Abs(TotalMinutes);  
					 Suffix = " from now";  
				 }  
				 return relativeTimes.First(n => TotalMinutes < n.Key).Value.Invoke(oSpan) + Suffix;  
		 }

		 public static string FormatDateTimeRelative(this FormHelper htmlHelper, DateTime? value)
		 {
			 if (value.HasValue)  
			 {
				 return FormatDateTimeRelative(htmlHelper, value.Value);
			 }
			 return string.Empty;
		 }

		 public static string FormatDateTimeRelativeHtml(this FormHelper htmlHelper, DateTime value)
		 {
			 return string.Format(@"<span title=""{0}"">{1}</span>", value, FormatDateTimeRelative(htmlHelper, value));
		 }
		 /// <summary>
		 /// Truncates the given text to fixed character length with trailing ellipsis.  
		 /// </summary>
		 /// <param name="htmlHelper">The HTML helper.</param>
		 /// <param name="text">The text.</param>
		 /// <param name="maxLength">Length of the max.</param>
		 /// <returns></returns>
		 public static string Truncate(this FormHelper htmlHelper, string text, int maxLength)  
		 {  
			 if (!string.IsNullOrEmpty(text))
				 return text.Length > maxLength ? text.Substring(0, maxLength) + "&hellip;" : text;  
			 return string.Empty;  
		 }

		 /// <summary>  
		 /// Truncate text by given input to 40 characters with trailing ellipsis.  
		 /// </summary>  
		 ///   <param name="htmlHelper"></param>  
		 ///   <param name="text"></param>  
		 /// <returns></returns>  
		 public static string Truncate(this FormHelper htmlHelper, string text)
		 {
			 return Truncate(htmlHelper, text, 40);
		 }  

  
		 #endregion  
	 }  
 }  
